#include "label_dialog.h"
#include <QMessageBox>
#include <regex>


void LabelQLineEdit::setListWidget(QListWidget* listWidget)
{
	this->listWidget = listWidget;
}

void LabelQLineEdit::keyPressEvent(QKeyEvent* e)
{
	if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down)
	{
		// Use QCoreApplication to send the event to the list widget
		QCoreApplication::sendEvent(listWidget, e);
	}
	else
	{
		QLineEdit::keyPressEvent(e);
	}
}

//LabelDialog::LabelDialog(const QString& text, QWidget* parent, QStringList labels, bool sortLabels, bool showTextField,
//                         const QString& completion, QMap<QString, QStringList> flags) : QDialog(parent),
//	sortLabels(sortLabels), flags(flags)
//{
//	QVBoxLayout* layout = new QVBoxLayout(this);
//
//	// Create the label input field
//	edit = new LabelQLineEdit();
//	edit->setPlaceholderText(text);
//	QRegularExpression regex("\\d*");
//	editGroupId = new QLineEdit();
//	editGroupId->setPlaceholderText("Group ID");
//	editGroupId->setValidator(new QRegularExpressionValidator(regex, this));
//
//	if (showTextField)
//	{
//		QHBoxLayout* layoutEdit = new QHBoxLayout();
//		layoutEdit->addWidget(edit, 6);
//		layoutEdit->addWidget(editGroupId, 2);
//		layout->addLayout(layoutEdit);
//	}
//
//	// Create buttons
//	buttonBox = new QDialogButtonBox(
//		QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
//		Qt::Horizontal, this
//	);
//	connect(buttonBox, &QDialogButtonBox::accepted, this, &LabelDialog::validate);
//	connect(buttonBox, &QDialogButtonBox::rejected, this, &LabelDialog::reject);
//	layout->addWidget(buttonBox);
//
//	// Create the label list
//	labelList = new QListWidget();
//	if (sortLabels)
//	{
//		labelList->addItems(labels);
//		labelList->sortItems();
//	}
//	else
//	{
//		labelList->addItems(labels);
//		labelList->setDragDropMode(QAbstractItemView::InternalMove);
//	}
//	labelList->setFixedHeight(150);
//	connect(labelList, &QListWidget::currentItemChanged, this, &LabelDialog::labelSelected);
//	connect(labelList, &QListWidget::itemDoubleClicked, this, &LabelDialog::labelDoubleClicked);
//	edit->setListWidget(labelList);
//	layout->addWidget(labelList);
//
//	// Setup flags
//	flagsLayout = new QVBoxLayout();
//	resetFlags();
//	layout->addLayout(flagsLayout);
//
//	// Description field
//	editDescription = new QTextEdit();
//	editDescription->setPlaceholderText("Label description");
//	editDescription->setFixedHeight(50);
//	layout->addWidget(editDescription);
//
//	// Setup completion
//	QCompleter* completer = new QCompleter(labelList->model(), this);
//	if (completion == "startswith")
//	{
//		completer->setCompletionMode(QCompleter::InlineCompletion);
//	}
//	else if (completion == "contains")
//	{
//		completer->setCompletionMode(QCompleter::PopupCompletion);
//		completer->setFilterMode(Qt::MatchContains);
//	}
//	else
//	{
//		qDebug() << "Unsupported completion mode: " << completion;
//	}
//	edit->setCompleter(completer);
//}
//
//void LabelDialog::addLabelHistory(const QString& label)
//{
//	if (!labelList->findItems(label, Qt::MatchExactly).isEmpty()) return;
//	labelList->addItem(label);
//	if (sortLabels) labelList->sortItems();
//}
//
//void LabelDialog::labelSelected(QListWidgetItem* item)
//{
//	edit->setText(item->text());
//}
//
//void LabelDialog::labelDoubleClicked(QListWidgetItem* item)
//{
//	validate();
//}
//
//void LabelDialog::validate()
//{
//	QString text = edit->text().trimmed();
//	if (!text.isEmpty())
//	{
//		accept();
//	}
//}
//
//void LabelDialog::resetFlags()
//{
//	deleteFlags();
//	// Implement logic to reset flags as per requirement
//}
//
//void LabelDialog::deleteFlags()
//{
//	while (QLayoutItem* item = flagsLayout->takeAt(0))
//	{
//		delete item->widget();
//		delete item;
//	}
//}

LabelDialog::LabelDialog(const QString& text, QWidget* parent, const QStringList& labels, bool sortLabels,
                         bool showTextField, const QString& completion, const QMap<QString, QStringList>& flags,
                         QMap<QString, bool> fitToContent): QDialog(parent), _fitToContent(fitToContent),
                                                            _sortLabels(sortLabels), _flags(flags)
{
	setWindowTitle("Label Dialog");

	// Text field for label
	edit = new QLineEdit(this);
	edit->setPlaceholderText(text);

	// Validator for group ID (only numbers)
	editGroupId = new QLineEdit(this);
	editGroupId->setPlaceholderText("Group ID");
	editGroupId->setValidator(new QRegularExpressionValidator(QRegularExpression("\\d*"), this));

	// Layout for the text fields
	QVBoxLayout* mainLayout = new QVBoxLayout(this);
	if (showTextField)
	{
		QHBoxLayout* textFieldLayout = new QHBoxLayout();
		textFieldLayout->addWidget(edit, 6);
		textFieldLayout->addWidget(editGroupId, 2);
		mainLayout->addLayout(textFieldLayout);
	}

	// Buttons (OK and Cancel)
	buttonBox = new QDialogButtonBox(
		QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
		Qt::Horizontal, this
	);
	connect(buttonBox, &QDialogButtonBox::accepted, this, &LabelDialog::validate);
	connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
	mainLayout->addWidget(buttonBox);

	// Label list
	labelList = new QListWidget(this);
	labelList->setFixedHeight(150);
	labelList->addItems(labels);
	if (_sortLabels)
	{
		labelList->sortItems();
	}
	else
	{
		labelList->setDragDropMode(QAbstractItemView::InternalMove);
	}
	mainLayout->addWidget(labelList);

	// Text edit for description
	editDescription = new QTextEdit(this);
	editDescription->setPlaceholderText("Label description");
	editDescription->setFixedHeight(50);
	mainLayout->addWidget(editDescription);

	// Flags layout
	flagsLayout = new QVBoxLayout();
	mainLayout->addLayout(flagsLayout);

	setLayout(mainLayout);

	// Completer for label suggestions
	QCompleter* completer = new QCompleter(labelList->model(), this);
	if (completion == "startswith")
	{
		completer->setCompletionMode(QCompleter::InlineCompletion);
	}
	else if (completion == "contains")
	{
		completer->setCompletionMode(QCompleter::PopupCompletion);
		completer->setFilterMode(Qt::MatchContains);
	}
	edit->setCompleter(completer);

	// Connections
	connect(edit, &QLineEdit::textChanged, this, &LabelDialog::updateFlags);
	connect(labelList, &QListWidget::currentItemChanged, this, &LabelDialog::labelSelected);
	connect(labelList, &QListWidget::itemDoubleClicked, this, &LabelDialog::labelDoubleClicked);
}

QString LabelDialog::getLabel() const
{
	return edit->text().trimmed();
}

int LabelDialog::getGroupId() const
{
	return editGroupId->text().isEmpty() ? -1 : editGroupId->text().toInt();
}

QString LabelDialog::getDescription() const
{
	return editDescription->toPlainText();
}

QMap<QString, bool> LabelDialog::getFlags() const
{
	QMap<QString, bool> result;
	for (int i = 0; i < flagsLayout->count(); ++i)
	{
		QCheckBox* checkbox = qobject_cast<QCheckBox*>(flagsLayout->itemAt(i)->widget());
		if (checkbox)
		{
			result[checkbox->text()] = checkbox->isChecked();
		}
	}
	return result;
}

void LabelDialog::resetFlags(const QString& label)
{
	QMap<QString, bool> flags;
	for (const QString& pattern : _flags.keys())
	{
		if (std::regex_match(label.toStdString(), std::regex(pattern.toStdString())))
		{
			for (const QString& key : _flags[pattern])
			{
				flags[key] = false;
			}
		}
	}
	setFlags(flags);
}

void LabelDialog::setFlags(const QMap<QString, bool>& flags)
{
	QLayoutItem* item;
	while ((item = flagsLayout->takeAt(0)) != nullptr)
	{
		delete item->widget();
		delete item;
	}
	for (auto it = flags.begin(); it != flags.end(); ++it)
	{
		QCheckBox* checkbox = new QCheckBox(it.key(), this);
		checkbox->setChecked(it.value());
		flagsLayout->addWidget(checkbox);
	}
}

void LabelDialog::validate()
{
	QString text = edit->text().trimmed();
	if (!text.isEmpty())
	{
		accept();
	}
	else
	{
		QMessageBox::warning(this, "Invalid Input", "Label cannot be empty!");
	}
}

LabelDialogPopUpResult LabelDialog::popUp(
    const QString& text,
    bool move,
    const QMap<QString, bool>& flags,
    int groupId,
    const QString& description
) {
    // Adjust list dimensions
    if (_fitToContent["row"]) {
        labelList->setMinimumHeight(labelList->sizeHintForRow(0) * labelList->count() + 2);
    }
    if (_fitToContent["column"]) {
        labelList->setMinimumWidth(labelList->sizeHintForColumn(0) + 2);
    }

    // Initialize fields
    editDescription->setPlainText(description);
    if (!flags.isEmpty()) {
        setFlags(flags);
    } else {
        resetFlags(text);
    }
    edit->setText(text);
    if (groupId == -1) {
        editGroupId->clear();
    } else {
        editGroupId->setText(QString::number(groupId));
    }

    QList<QListWidgetItem*> items = labelList->findItems(text, Qt::MatchFixedString);
    if (!items.isEmpty()) {
        labelList->setCurrentItem(items.first());
    }

    edit->setFocus();
    if (move) {
        move(QCursor::pos());
    }

    // Execute dialog and return result
    if (exec() == QDialog::Accepted) {
        return {
            edit->text().trimmed(),
            getFlags(),
            getGroupId(),
            editDescription->toPlainText()
        };
    }

    // If cancelled
    return { QString(), QMap<QString, bool>(), -1, QString() };
}

void LabelDialog::labelSelected(QListWidgetItem* item)
{
	if (item)
	{
		edit->setText(item->text());
	}
}

void LabelDialog::labelDoubleClicked(QListWidgetItem*)
{
	validate();
}

void LabelDialog::updateFlags(const QString& label)
{
	QMap<QString, bool> newFlags;
	for (const QString& pattern : _flags.keys())
	{
		if (std::regex_match(label.toStdString(), std::regex(pattern.toStdString())))
		{
			for (const QString& key : _flags[pattern])
			{
				newFlags[key] = false;
			}
		}
	}
	setFlags(newFlags);
}
